/* ast.c
 * 
 */

#include <stdio.h>
#include <stdlib.h>

#include "ast.h"

ASTTREE createNode(int type,
		   int vtype,
		   int ival,
		   char* sval,
           int bval,
		   ASTTREE left,
		   ASTTREE right)
{
  /*printf(";[DEBUG] createNode [type=%d:%s] [vtype=%d] [ival=%d]  [sval=%s] [bval=%d]  \n",type,humanReadableNodeType(type),vtype ,ival,sval, bval);*/
  
  ASTTREE node = (ASTTREE) malloc(sizeof(ASTNODE));
  if (node == NULL)
    {
      fprintf(stderr,"KO\n");
      printf("ERROR : malloc failed in createNode(..)\n");
      exit(1);
    }
  else
    {
      node->type = type;
	  node->vtype = vtype;
      node->ival = ival;
      node->sval = sval;
      node->bval = bval;
      node->left = left;
      node->right = right;
        //printTree(node);
      return node;
    }
    
}

void freeNode(ASTTREE node)
{
  if (node != NULL)
    {
      if (node->sval != NULL) free(node->sval);
      if (node->left != NULL) freeNode(node->left);
      if (node->right != NULL) freeNode(node->right);

      free(node);
    }
}

void freeTree(ASTTREE tree) // idem above but top root is static
{
  if (tree != NULL)
    {
      if (tree->sval != NULL) free(tree->sval);
      if (tree->left != NULL) freeNode(tree->left);
      if (tree->right != NULL) freeNode(tree->right);
    } 
}


char* humanReadableNodeType(int type)
{
 //printf(";[DEBUG] humanReadableNodeType %d\n",type);
  switch(type) {

      case AT_ID:      return "AT_ID"; 
      case AT_NB:       return "AT_NB"; 
      case AT_OPADD:    return "AT_OPADD"; 
      case AT_OPSUB:    return "AT_OPSUB"; 
      case AT_OPMUL :   return "AT_OPMUL"; 
      case AT_OPDIV :   return "AT_OPDIV"; 
      case AT_OPWRITE : return "AT_OPPWRITE"; 
      case AT_OPREAD :  return "AT_OPREAD"; 
      case AT_OPASS :   return "AT_OPASS"; 
      case AT_ILIST :   return "AT_ILIST"; 
      case AT_OPEQ:    return "AT_OPEQ"; 
      case AT_BOOL:     return "AT_BOOL"; 
      case AT_LT:     return "AT_LT"; 
      case AT_LE:     return "AT_LE"; 
      case AT_OR:     return "AT_OR"; 
      case AT_AND:     return "AT_AND"; 
      case AT_NOT:     return "AT_NOT"; 
      case AT_DECLARE:     return "AT_DECLARE"; 
      case AT_DECLARE_BLOC: return "AT_DECLARE_BLOC"; 
      case AT_FUNC_HEAD:    return "AT_FUNC_HEAD"; 
      case AT_FUNC_BODY:    return "AT_FUNC_BODY"; 
      case AT_FUNC:         return "AT_FUNC"; 
      case AT_IF:	  		return "AT_IF"; 
      case AT_IF_BODY:	  	return "AT_IF_BODY"; 
      case AT_WHILE:   	return "AT_WHILE"; 
      case AT_ARGS:	  return "AT_ARGS"; 
      case AT_IMPL:   return "AT_IMPL"; 
      case AT_PROG:   return "AT_PROG"; 
      case AT_UNKNOWN:  return "AT_UNKOWN"; 
      case AT_ISET:     return "AT_ISET";
      case AT_VOID:     return "AT_VOID";
      case AT_NEG:      return "AT_NEG";
      case AT_RETURN:   return "AT_RETURN";
      case AT_FUNC_CALL : return "AT_FUNC_CALL"; 
      case AT_DEL_FROM : return "AT_DEL_FROM";   
      case AT_ADD_TO :   return "AT_ADD_TO";
      case AT_SHARP : return "AT_SHARP";
      case AT_IN :  return "AT_IN";
      default :         return "??";
  }
}






void printTree(ASTTREE tree)
{
  if (tree != NULL) 
    {
      printf("; [%p] type=%s,[vtype=%d], ival=%d, sval=", tree, humanReadableNodeType(tree->type),tree->vtype, tree->ival);
      if (tree->sval == NULL) printf("NULL");
      else printf("'%s'", tree->sval);
        printf(",bval=%d, left=%p, right=%p\n",tree->bval, tree->left, tree->right);

      printTree(tree->left);
      printTree(tree->right);
    }
}


void printTreeXML(ASTTREE tree, char *outFile_AST_XML)
{
	//EFFECT: PRINT ASTTREE in XML Format <root><node><type>...></node></root>   to the file outFile_AST_XML
  if (tree != NULL) 
    {      
    		char myBuf[20];
    		  
	        writeToFile(outFile_AST_XML,"\n<node>");
    	 
            //print type node
    	    writeToFile(outFile_AST_XML, "\n<type>");
    	    writeToFile(outFile_AST_XML,humanReadableNodeType(tree->type));
    	    writeToFile(outFile_AST_XML, "</type>");
            
			//print virtual type
			writeToFile(outFile_AST_XML, "\n<vtype>");
			sprintf(myBuf, "%d",  tree->vtype );
    	    writeToFile(outFile_AST_XML,myBuf);
    	    writeToFile(outFile_AST_XML, "</vtype>");
    	  
            //print addresse
    	   	writeToFile(outFile_AST_XML, "\n<addr>");    	   		 
            sprintf(myBuf, "%p",  tree );
			writeToFile(outFile_AST_XML, myBuf  );
    	   	writeToFile(outFile_AST_XML, "</addr>");
        
            //print boolean value
            writeToFile(outFile_AST_XML, "\n<bval>"); 
            if(tree->bval==-1) 	writeToFile(outFile_AST_XML,"UNDIF_BOOL");
            else if(tree->bval==0) 	writeToFile(outFile_AST_XML,"FALSE");
            if(tree->bval==1) 	writeToFile(outFile_AST_XML,"TRUE");					
            writeToFile(outFile_AST_XML, "</bval>");
        
            //print  string value
            writeToFile(outFile_AST_XML, "\n<sval>");
            if (tree->sval != NULL) writeToFile(outFile_AST_XML,  tree->sval);
            else  writeToFile(outFile_AST_XML, "NULL");
            writeToFile(outFile_AST_XML, "</sval>");
        
            //print int value
            writeToFile(outFile_AST_XML, "\n<ival>");					  
            sprintf(myBuf, "%d",  tree->ival);
            writeToFile(outFile_AST_XML, myBuf  );
            writeToFile(outFile_AST_XML, "</ival>");

        
            //print left child
            writeToFile(outFile_AST_XML, "\n<left>");				  
            if(tree->left != NULL) {
                printTreeXML(tree->left,outFile_AST_XML);  
            } else  
                writeToFile(outFile_AST_XML, "NULL");
            writeToFile(outFile_AST_XML, "</left>");
				
            //print right child
            writeToFile(outFile_AST_XML, "\n<right>");
            if(tree->right != NULL)   {
                printTreeXML(tree->right,outFile_AST_XML);  
            } else  
                writeToFile(outFile_AST_XML, "NULL");
            writeToFile(outFile_AST_XML, "</right>");
					
            writeToFile(outFile_AST_XML,"\n</node>");
    	  
    	 
           
        
        
    }
    
     
}

 

void writeToFile(char *outFile, char *textToWrite)
{	//EFFECT: append textToWrite to outFile
	
		  FILE *fp;
			fp=fopen(outFile, "a");
			  
      fprintf(fp,"%s",textToWrite  );
    	
    	fclose(fp);    		
}

ASTTREE inTree(ASTTREE tree, char* node, int vtype)
{	
	if (tree != NULL) 
    {
		/*printf("[inTree] [tree sval,vtype]%s %d [look] %s %d \n",tree->sval,tree->vtype,node, vtype);*/
		if (tree->sval != NULL && strcmp(tree->sval,node) == 0 && tree->vtype == vtype) return tree;
		
		ASTTREE left = inTree(tree->left,node,vtype);
		if ( left != NULL ) return inTree(left, node, vtype);
		else return inTree(tree->right, node,vtype);
    }
}    
